package com.yungam.imcs.controller.quality;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.influxdb.query.FluxRecord;
import com.influxdb.query.FluxTable;
import com.yungam.common.bean.equip.Equipment;
import com.yungam.common.bean.process.ProductProcess;
import com.yungam.common.bean.process.ProductionProcess;
import com.yungam.common.bean.product.ProductionProduct;
import com.yungam.common.response.RetDTO;
import com.yungam.common.service.EquipmentService;
import com.yungam.common.service.ProductProcessService;
import com.yungam.common.service.ProductionProcessService;
import com.yungam.common.service.ProductionProductService;
import com.yungam.influxdb.service.InfluxdbCommonService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;

@Api(tags = "质量数据包页面接口")
@Slf4j
@RestController
@RequestMapping("/dataPackage")
public class DataPackageController {

    @Resource
    private ProductionProductService productionProductService;
    @Resource
    private ProductProcessService productProcessService;
    @Resource
    private ProductionProcessService productionProcessService;
    @Resource
    private EquipmentService equipmentService;
    @Resource
    private InfluxdbCommonService commonService;

    private Map<String, List<Object>> process0fAll;

    // 定时获取所有的工序信息
    @Scheduled(fixedRate = 1000 * 60 * 5)
    private void taskWithProcess() {
        // 处理所有的工序, 按照所属 productNo 存入 Map
        Map<String, List<Object>> cur = new HashMap<>();
        List<ProductProcess> allProcess = productProcessService.list();
        for (ProductProcess pr : allProcess) {
            String productNo = pr.getProductNo();
            List<Object> list = cur.getOrDefault(productNo, new ArrayList<>());
            Map<String, String> item = new HashMap<>();
            item.put("processNo", pr.getProcessNo());
            item.put("processName", pr.getProcessName());
            list.add(item);
            cur.put(productNo, list);
        }
        this.process0fAll = cur;
    }

    /* 根据时间范围-获取产品信息 */
    @ApiOperation("获取产品信息")
    @GetMapping("/getProductInfo")
    public RetDTO<?> getProductInfo(@ApiParam("开始时间") String start,
                                    @ApiParam("结束时间") String end) {
        QueryWrapper<ProductionProduct> qw = new QueryWrapper<>();
        // 拼接查询条件
        if (StringUtils.isNotEmpty(start)
        && StringUtils.isNotEmpty(end)) {
            start += " 00:00:00"; end += " 23:59:59";
            qw.between("start_time", start, end);
        }
        //
        List<ProductionProduct> products = productionProductService.list(qw);
        if (products.size() == 0) return RetDTO.data(null);

        //
        List<Object> ans = Lists.newArrayList(); // 返回值

        Map<String, List<Object>> cur = this.process0fAll;
        Map<String, Object> container = Maps.newHashMap();
        // 按照 productNo & productSn 整合
        for (ProductionProduct product : products) {
            Map<String, Object> map = Maps.newHashMap();
            String productSn = product.getProductSn(), productNo = product.getProductNo();
            map.put("productSn", productSn); // 罐号
            map.put("children", cur.getOrDefault(productNo, null));

            container.put(productSn, map);
        }

        Map<String, List<Object>> pMap = Maps.newHashMap();
        for (ProductionProduct product : products) {
            String productSn = product.getProductSn(), productNo = product.getProductNo();
            if (!container.containsKey(productSn)) continue;

            List<Object> list = pMap.getOrDefault(productNo, Lists.newArrayList());
            list.add(container.get(productSn));
            pMap.put(productNo, list);
        }

        for (String s : pMap.keySet()) {
            Map<String, Object> item = Maps.newHashMap();
            List<Object> list = pMap.get(s);
            item.put("productNo", s); // 罐号
            item.put("children", list);
            ans.add(item);
        }

        return RetDTO.data(ans);
    }

    /* 获取工序的参数信息 */
    /* 从 influxdb 获取数据
    *   根据 args  => 设备号 => ip
    *   根据 ip 去 influxdb 查询参数及值
    * */
    @ApiOperation("获取工序参数 & 值等信息")
    @GetMapping("/queryProcessParams")
    public RetDTO<?> queryProcessParams(@ApiParam("罐号") String productSn,
                                        @ApiParam("工序号") String processNo) {
        List<ProductionProcess> list = productionProcessService.list(new QueryWrapper<ProductionProcess>().eq("product_sn", productSn)
                .eq("process_no", processNo));
        if (list.size() == 0) return RetDTO.data(null);
        ProductionProcess pp = list.get(0);
        if (pp.getStartTime() == null || pp.getEndTime() == null) {
            if (list.size() == 1) return RetDTO.data(null);
            else {
                pp = list.get(1);
                if (pp.getStartTime() == null || pp.getEndTime() == null) return RetDTO.data(null);
            }
        }

        // 通过设备号去找 ip
        String equNo = pp.getEquNo();
        Equipment equipment = equipmentService.getOne(new QueryWrapper<Equipment>().eq("equ_number", equNo));
        if (equipment == null)  return RetDTO.data(null);

        String ip = equipment.getEquIp();
        Long[] range = { pp.getStartTime().getTime() / 1000, pp.getEndTime().getTime() / 1000 };

        Map<String, Object> nameMap = Maps.newHashMap();
        Map<String, List<Object>> valueMap = Maps.newHashMap();

        List<FluxTable> tables = commonService.queryByIp(ip, range, null);

        for (FluxTable table : tables) {
            List<FluxRecord> records = table.getRecords();
            for (FluxRecord fluxRecord : records) {
                // id
                String id = String.valueOf(fluxRecord.getValues().get("id"));
                // name
                Object name = fluxRecord.getValues().get("name");
                // value
                Object value = fluxRecord.getValues().get("_value");
                if (Objects.isNull(value)) value = 0d;
                else {
                    Double d = (Double) value;
                    String format = String.format("%.2f", d);
                    value = Double.parseDouble(format);
                }

                nameMap.put(id, name);
                List<Object> od = valueMap.getOrDefault(id, Lists.newArrayList());
                od.add(value);
                valueMap.put(id, od);
            }
        }

        Map<String, Object> ans = Maps.newHashMap();
        ans.put("startTime", pp.getStartTime());
        ans.put("params", nameMap);
        ans.put("value", valueMap);
        return RetDTO.data(ans);
    }

}

